home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / clients / bitmap / graphics.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-12  |  42.0 KB  |  1,600 lines

  1. /*
  2.  * $XConsortium: Graphics.c,v 1.15 91/07/24 15:24:24 converse Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Davor Matic, MIT X Consortium
  24.  */
  25.  
  26. #include <X11/StringDefs.h>
  27. #ifdef MSDOS
  28. #include "X11/IntrinsP.h"      /* QDK 05/11/1994 10:44am. */
  29. #else
  30. #include "X11/IntrinsicP.h"
  31. #endif
  32. #include <X11/Xfuncs.h>
  33. #include "BitmapP.h"
  34.     
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <math.h>
  38.  
  39. #ifndef abs
  40. #define abs(x)                        (((x) > 0) ? (x) : -(x))
  41. #endif
  42. #define min(x, y)                     (((int)(x) < (int)(y)) ? (x) : (y))
  43. #define max(x, y)                     (((int)(x) > (int)(y)) ? (x) : (y))
  44. #ifndef rint
  45. #define rint(x)                       floor(x + 0.5)
  46. #endif
  47.  
  48. /*****************************************************************************\
  49.  *                                   Graphics                                *
  50. \*****************************************************************************/
  51.  
  52. #define GetBit(image, x, y)\
  53.     ((bit)((*(image->data + (x) / 8 + (y) * image->bytes_per_line) &\
  54.         (1 << ((x) % 8))) ? 1 : 0))
  55.  
  56.  
  57. bit BWGetBit(w, x, y)
  58.     Widget  w;
  59.      Position      x, y;
  60. {
  61.     BitmapWidget BW = (BitmapWidget) w;
  62.     
  63.     if (QueryInBitmap(BW, x, y))
  64.     return GetBit(BW->bitmap.image, x, y);
  65.     else
  66.     return NotSet;
  67. }
  68.  
  69.  
  70. #define InvertBit(image, x, y)\
  71.     (*(image->data + (x) / 8 + (y) * image->bytes_per_line) ^=\
  72.      (bit) (1 << ((x) % 8)))
  73.  
  74.  
  75. #define SetBit(image, x, y)\
  76.     (*(image->data + (x) / 8 + (y) * image->bytes_per_line) |=\
  77.      (bit) (1 << ((x) % 8)))
  78.  
  79. #define ClearBit(image, x, y)\
  80.     (*(image->data + (x) / 8 + (y) * image->bytes_per_line) &=\
  81.      (bit)~(1 << ((x) % 8)))
  82.  
  83.  
  84. #define HighlightSquare(BW, x, y)\
  85.     XFillRectangle(XtDisplay(BW), XtWindow(BW),\
  86.                    BW->bitmap.highlighting_gc,\
  87.            InWindowX(BW, x), InWindowY(BW, y),\
  88.                    BW->bitmap.squareW, BW->bitmap.squareH)
  89. /*
  90. void HighlightSquare(BW, x, y)
  91.     BitmapWidget BW;
  92.     Position x, y;
  93. {
  94.     XFillRectangle(XtDisplay(BW), XtWindow(BW),
  95.                    BW->bitmap.highlighting_gc,
  96.            InWindowX(BW, x), InWindowY(BW, y),
  97.                    BW->bitmap.squareW, BW->bitmap.squareH);
  98. }
  99. */
  100.  
  101. #define DrawSquare(BW, x, y)\
  102.     XFillRectangle(XtDisplay(BW), XtWindow(BW),\
  103.                    BW->bitmap.drawing_gc,\
  104.            InWindowX(BW, x), InWindowY(BW, y),\
  105.                    BW->bitmap.squareW, BW->bitmap.squareH) 
  106.  
  107. /*
  108. void DrawSquare(BW, x, y)
  109.     BitmapWidget BW;
  110.     Position x, y;
  111. {
  112.     XFillRectangle(XtDisplay(BW), XtWindow(BW),
  113.                    BW->bitmap.drawing_gc,
  114.            InWindowX(BW, x), InWindowY(BW, y),
  115.                    BW->bitmap.squareW, BW->bitmap.squareH);
  116. }
  117. */
  118.  
  119. #define InvertPoint(BW, x, y)\
  120.     {InvertBit(BW->bitmap.image, x, y); DrawSquare(BW, x, y);}
  121.  
  122. #define DrawPoint(BW, x, y, value)\
  123.     if (GetBit(BW->bitmap.image, x, y) != value)\
  124.        InvertPoint(BW, x, y)
  125.  
  126. void BWDrawPoint(w, x, y, value)
  127.     Widget  w;
  128.     Position      x, y;
  129.     bit           value;
  130. {
  131.     BitmapWidget BW = (BitmapWidget) w;
  132.     
  133.     if (QueryInBitmap(BW, x, y)) {
  134.     if (value == Highlight)
  135.         HighlightSquare(BW, x, y);
  136.     else
  137.         DrawPoint(BW, x, y, value);
  138.     }
  139. }
  140.  
  141. XPoint *HotSpotShape(BW, x ,y)
  142.     BitmapWidget BW;
  143.     Position     x, y;
  144. {
  145.     static XPoint points[5];
  146.   
  147.     points[0].x = InWindowX(BW, x);
  148.     points[0].y = InWindowY(BW, y + 1.0/2);
  149.     points[1].x = InWindowX(BW, x + 1.0/2);
  150.     points[1].y = InWindowY(BW, y + 1);
  151.     points[2].x = InWindowX(BW, x + 1);
  152.     points[2].y = InWindowY(BW, y + 1.0/2);
  153.     points[3].x = InWindowX(BW, x + 1.0/2);
  154.     points[3].y = InWindowY(BW, y);
  155.     points[4].x = InWindowX(BW, x);
  156.     points[4].y = InWindowY(BW, y + 1.0/2);
  157.     
  158.     return points;
  159. }
  160.  
  161. #define DrawHotSpot(BW, x, y)\
  162.   XFillPolygon(XtDisplay(BW), XtWindow(BW), BW->bitmap.drawing_gc,\
  163.            HotSpotShape(BW, x, y), 5, Convex, CoordModeOrigin)
  164.  
  165. #define HighlightHotSpot(BW, x, y)\
  166.   XFillPolygon(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,\
  167.            HotSpotShape(BW, x, y), 5, Convex, CoordModeOrigin)
  168.  
  169. XImage *CreateBitmapImage();
  170. void DestroyBitmapImage();
  171.  
  172. void BWRedrawHotSpot(w)
  173.     Widget w;
  174. {
  175.     BitmapWidget BW = (BitmapWidget) w;
  176.  
  177.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y))
  178.     DrawHotSpot(BW, BW->bitmap.hot.x, BW->bitmap.hot.y);
  179. }
  180.  
  181. void BWClearHotSpot(w)
  182.     Widget w;
  183. {
  184.     BitmapWidget BW = (BitmapWidget) w;
  185.     
  186.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) {
  187.       DrawHotSpot(BW, BW->bitmap.hot.x, BW->bitmap.hot.y);
  188.       BW->bitmap.hot.x = BW->bitmap.hot.y = NotSet;
  189.     }
  190. }
  191.  
  192. void BWDrawHotSpot(w, x, y, value)
  193.     Widget w;
  194.     Position x, y;
  195.     int  value;
  196. {
  197.     BitmapWidget BW = (BitmapWidget) w;
  198.     
  199.     if (QueryInBitmap(BW, x, y)) {
  200.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) &&
  201.         ((BW->bitmap.hot.x == x) && (BW->bitmap.hot.y == y))) {
  202.         if ((value == Clear) || (value == Invert)) {
  203.         BWClearHotSpot(w);
  204.         }
  205.     }
  206.     else
  207.         if ((value == Set) || (value == Invert)) {
  208.         BWClearHotSpot(w);
  209.         DrawHotSpot(BW, x, y);
  210.         BW->bitmap.hot.x = x;
  211.         BW->bitmap.hot.y = y;
  212.         }
  213.     
  214.     if (value == Highlight)
  215.         HighlightHotSpot(BW, x, y); 
  216.     }
  217. }
  218.  
  219. void BWSetHotSpot(w, x, y)
  220.     Widget w;
  221.     Position x, y;
  222. {
  223.     if (QuerySet(x, y))
  224.     BWDrawHotSpot(w, x, y, Set);
  225.     else
  226.     BWClearHotSpot(w);
  227. }
  228.  
  229. /* high level procedures */
  230.  
  231. void BWRedrawSquares(w, x, y, width, height)
  232.     Widget  w;
  233.     register Position x, y;
  234.     Dimension width, height;
  235. {
  236.     BitmapWidget BW = (BitmapWidget) w;
  237.     Position from_x = InBitmapX(BW, x);
  238.     Position from_y = InBitmapY(BW, y);
  239.     Position to_x = InBitmapX(BW, x + width);
  240.     Position to_y = InBitmapY(BW, y + height);
  241.  
  242.     QuerySwap(from_x, to_x);
  243.     QuerySwap(from_y, to_y);
  244.     from_x = max(0, from_x);
  245.     from_y = max(0, from_y);
  246.     to_x = min(BW->bitmap.image->width - 1, to_x);
  247.     to_y = min(BW->bitmap.image->height - 1, to_y);
  248.   
  249.     for (x = from_x; x <= to_x; x++)
  250.     for (y = from_y; y <= to_y; y++)
  251.         if (GetBit(BW->bitmap.image, x, y)) DrawSquare(BW, x, y);
  252. }
  253.  
  254. void BWDrawGrid(w, from_x, from_y, to_x, to_y)
  255.      Widget w;
  256.      Position from_x, from_y,
  257.               to_x, to_y;
  258. {
  259.     BitmapWidget BW = (BitmapWidget) w;
  260.     int i;
  261.   
  262.     QuerySwap(from_x, to_x);
  263.     QuerySwap(from_y, to_y);
  264.     from_x = max(0, from_x);
  265.     from_y = max(0, from_y);
  266.     to_x = min(BW->bitmap.image->width - 1, to_x);
  267.     to_y = min(BW->bitmap.image->height - 1, to_y);
  268.   
  269.     for(i = from_x + (from_x == 0); i <= to_x; i++)
  270.     XDrawLine(XtDisplay(BW), XtWindow(BW), 
  271.           BW->bitmap.frame_gc,
  272.           InWindowX(BW, i), InWindowY(BW, from_y),
  273.           InWindowX(BW, i), InWindowY(BW, to_y + 1));
  274.   
  275.     for(i = from_y + (from_y == 0); i <= to_y; i++)
  276.     XDrawLine(XtDisplay(BW), XtWindow(BW), 
  277.           BW->bitmap.frame_gc,
  278.           InWindowX(BW, from_x), InWindowY(BW, i),
  279.           InWindowX(BW, to_x + 1), InWindowY(BW, i));
  280. }
  281.  
  282.  
  283. void BWRedrawGrid(w, x, y, width, height)
  284.     Widget w;
  285.     Position x, y;
  286.     Dimension width, height;
  287. {
  288.     BitmapWidget BW = (BitmapWidget) w;
  289.     Position from_x = InBitmapX(BW, x);
  290.     Position from_y = InBitmapY(BW, y);
  291.     Position to_x = InBitmapX(BW, x + width);
  292.     Position to_y = InBitmapY(BW, y + height);
  293.  
  294.     if (BW->bitmap.grid)
  295.     BWDrawGrid(w, from_x, from_y, to_x, to_y);
  296. }
  297.  
  298. void BWDrawLine(w, from_x, from_y, to_x, to_y, value)
  299.     Widget  w;
  300.     Position      from_x, from_y,
  301.                   to_x, to_y;
  302.     int           value;
  303. {
  304.     Position i;
  305.     register double x, y;
  306.     double dx, dy, delta;
  307.  
  308.     dx = to_x - from_x;
  309.     dy = to_y - from_y;
  310.     x = from_x + 0.5;
  311.     y = from_y + 0.5;
  312.     delta = max(abs(dx), abs(dy));
  313.     if (delta > 0) {
  314.     dx /= delta;
  315.     dy /= delta;
  316.     for(i = 0; i <= delta; i++) {
  317.         BWDrawPoint(w, (Position) x, (Position) y, value);
  318.         x += dx;
  319.         y += dy;
  320.     }
  321.     }
  322.     else
  323.     BWDrawPoint(w, from_x, from_y, value);
  324. }
  325.  
  326. void BWBlindLine(w, from_x, from_y, to_x, to_y, value)
  327.     Widget  w;
  328.     Position      from_x, from_y,
  329.                   to_x, to_y;
  330.     int           value;
  331. {
  332.     Position i;
  333.     register double x, y;
  334.     double dx, dy, delta;
  335.  
  336.     dx = to_x - from_x;
  337.     dy = to_y - from_y;
  338.     x = from_x + 0.5;
  339.     y = from_y + 0.5;
  340.     delta = max(abs(dx), abs(dy));
  341.     if (delta > 0) {
  342.     dx /= delta;
  343.     dy /= delta;
  344.     x += dx;
  345.     y += dy;
  346.     for(i = 1; i <= delta; i++) {
  347.         BWDrawPoint(w, (Position) x, (Position) y, value);
  348.         x += dx;
  349.         y += dy;
  350.     }
  351.     }
  352.     else
  353.     BWDrawPoint(w, from_x, from_y, value);
  354. }
  355.  
  356. void BWDrawRectangle(w, from_x, from_y, to_x, to_y, value)
  357.     Widget w;
  358.     Position     from_x, from_y,
  359.     to_x, to_y;
  360.     int          value;
  361. {
  362.     register Position i;
  363.     Dimension delta, width, height;
  364.     
  365.     QuerySwap(from_x, to_x);
  366.     QuerySwap(from_y, to_y);
  367.     
  368.     width = to_x - from_x;
  369.     height = to_y - from_y;
  370.  
  371.     delta = max(width, height);
  372.     
  373.     if (!QueryZero(width, height)) {
  374.     for (i = 0; (int)i < (int)delta; i++) {
  375.         if ((int)i < (int)width) {
  376.         BWDrawPoint(w, from_x + i, from_y, value);
  377.         BWDrawPoint(w, to_x - i, to_y, value);
  378.         }
  379.         if ((int)i < (int)height) {
  380.         BWDrawPoint(w, from_x, to_y - i, value);
  381.         BWDrawPoint(w, to_x, from_y + i, value);
  382.         }
  383.     }
  384.     }
  385.     else
  386.     BWDrawLine(w, 
  387.            from_x, from_y, 
  388.            to_x, to_y, value);
  389. }
  390.   
  391. void BWDrawFilledRectangle(w, from_x, from_y, to_x, to_y, value)
  392.     Widget   w;
  393.     Position from_x, from_y,
  394.          to_x, to_y;
  395.     int      value;
  396. {
  397.     register Position x, y;
  398.  
  399.     QuerySwap(from_x, to_x);
  400.     QuerySwap(from_y, to_y);
  401.     
  402.     for (x = from_x; x <= to_x; x++)
  403.     for (y = from_y; y <= to_y; y++)
  404.         BWDrawPoint(w, x, y, value);
  405. }
  406.  
  407. void BWDrawCircle(w, origin_x, origin_y, point_x, point_y, value)
  408.     Widget  w;
  409.     Position      origin_x, origin_y,
  410.     point_x, point_y;
  411.     int           value;
  412. {
  413.     register Position i, delta;
  414.     Dimension dx, dy, half;
  415.     double radius;
  416.     
  417.     dx = abs(point_x - origin_x);
  418.     dy = abs(point_y - origin_y);
  419.     radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy));
  420.     if (radius < 1.0) {
  421.     BWDrawPoint(w, origin_x, origin_y, value);
  422.     }
  423.     else {
  424.     BWDrawPoint(w, origin_x - (Position) floor(radius), origin_y, value);
  425.     BWDrawPoint(w, origin_x + (Position) floor(radius), origin_y, value);
  426.     BWDrawPoint(w, origin_x, origin_y - (Position) floor(radius), value);
  427.     BWDrawPoint(w, origin_x, origin_y + (Position) floor(radius), value);
  428.     }
  429.     half = radius / sqrt(2.0);
  430.     for(i = 1; (int)i <= (int)half; i++) {
  431.     delta = sqrt(radius * radius - i * i);
  432.     BWDrawPoint(w, origin_x - delta, origin_y - i, value);
  433.     BWDrawPoint(w, origin_x - delta, origin_y + i, value);
  434.     BWDrawPoint(w, origin_x + delta, origin_y - i, value);
  435.     BWDrawPoint(w, origin_x + delta, origin_y + i, value);
  436.     if (i != delta) {
  437.         BWDrawPoint(w, origin_x - i, origin_y - delta, value);
  438.         BWDrawPoint(w, origin_x - i, origin_y + delta, value);
  439.         BWDrawPoint(w, origin_x + i, origin_y - delta, value);
  440.         BWDrawPoint(w, origin_x + i, origin_y + delta, value);
  441.     }
  442.     }
  443. }
  444.  
  445. void BWDrawFilledCircle(w, origin_x, origin_y, point_x, point_y, value)
  446.     Widget  w;
  447.     Position      origin_x, origin_y,
  448.               point_x, point_y;
  449.     int           value;
  450. {
  451.     register Position i, j, delta;
  452.     Dimension dx, dy;
  453.     double radius;
  454.     
  455.     dx = abs(point_x - origin_x);
  456.     dy = abs(point_y - origin_y);
  457.     radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy));
  458.     for(j = origin_x - (Position) floor(radius); 
  459.     j <= origin_x + (Position) floor(radius); j++)
  460.     BWDrawPoint(w, j, origin_y, value);
  461.     for(i = 1; i <= (Position) floor(radius); i++) {
  462.     delta = sqrt(radius * radius - i * i);
  463.     for(j = origin_x - delta; j <= origin_x + delta; j++) {
  464.         BWDrawPoint(w, j, origin_y - i, value);
  465.         BWDrawPoint(w, j, origin_y + i, value);
  466.     }
  467.     }
  468. }
  469.  
  470. #define QueryFlood(BW, x, y, value)\
  471.     ((GetBit(BW->bitmap.image, x, y) !=\
  472.       (value & 1)) && QueryInBitmap(BW, x, y))
  473.  
  474. #define Flood(BW, x, y, value)\
  475.     {if (value == Highlight) HighlightSquare(BW, x, y);\
  476.      else InvertPoint(BW, x, y);}
  477.  
  478. /*
  479. void FloodLoop(BW, x, y, value)
  480.     BitmapWidget  BW;
  481.     Position      x, y;
  482.     int           value;
  483. {
  484.     if (QueryFlood(BW, x, y, value)) {
  485.     Flood(BW, x, y, value);
  486.     FloodLoop(BW, x, y - 1, value);
  487.     FloodLoop(BW, x - 1, y, value);
  488.     FloodLoop(BW, x, y + 1, value);
  489.     FloodLoop(BW, x + 1, y, value);
  490.     }
  491. }
  492. */
  493.  
  494. void FloodLoop(BW, x, y, value)
  495.     BitmapWidget BW;
  496.     Position     x, y;
  497.     int          value;
  498. {
  499.     Position save_x, save_y, x_left, x_right;
  500.     
  501.     if (QueryFlood(BW, x, y, value)) 
  502.     Flood(BW, x, y, value)
  503.  
  504.  
  505.     save_x = x;
  506.     save_y = y;
  507.  
  508.     x++;
  509.     while (QueryFlood(BW, x, y, value)) {
  510.     Flood(BW, x, y, value);
  511.     x++;
  512.     }
  513.     x_right = --x;
  514.  
  515.     x = save_x;
  516.     x--;
  517.     while (QueryFlood(BW, x, y, value)) {
  518.     Flood(BW, x, y, value);
  519.     x--;
  520.     }
  521.     x_left = ++x;
  522.  
  523.  
  524.     x = x_left;
  525.     y = save_y;
  526.     y++;
  527.     
  528.     while (x <= x_right) {
  529.     Boolean flag = False;
  530.     Position x_enter;
  531.     
  532.     while (QueryFlood(BW, x, y, value) && (x <= x_right)) {
  533.         flag = True;
  534.         x++;
  535.     }
  536.     
  537.     if (flag) {
  538.         if ((x == x_right) && QueryFlood(BW, x, y, value))
  539.         FloodLoop(BW, x, y, value);
  540.         else
  541.         FloodLoop(BW, x - 1, y, value);
  542.     }
  543.     
  544.     x_enter = x;
  545.     
  546.     while (!QueryFlood(BW, x, y, value) && (x < x_right))
  547.         x++;
  548.     
  549.     if (x == x_enter) x++;
  550.     }
  551.  
  552.     x = x_left;
  553.     y = save_y;
  554.     y--;
  555.  
  556.     while (x <= x_right) {
  557.     Boolean flag = False;
  558.     Position x_enter;
  559.     
  560.     while (QueryFlood(BW, x, y, value) && (x <= x_right)) {
  561.         flag = True;
  562.         x++;
  563.     }
  564.     
  565.     if (flag) {
  566.         if ((x == x_right) && QueryFlood(BW, x, y, value))
  567.         FloodLoop(BW, x, y, value);
  568.         else
  569.         FloodLoop(BW, x - 1, y, value);
  570.     }
  571.     
  572.     x_enter = x;
  573.     
  574.     while (!QueryFlood(BW, x, y, value) && (x < x_right))
  575.         x++;
  576.     
  577.     if (x == x_enter) x++;
  578.     }
  579. }
  580.  
  581. void BWFloodFill(w, x, y, value)
  582.     Widget  w;
  583.     Position      x, y;
  584.     int           value;
  585. {
  586.     BitmapWidget BW = (BitmapWidget) w;
  587.     int pixel;
  588.  
  589.     pixel = GetBit(BW->bitmap.image, x, y);
  590.  
  591.     if (value == Invert)
  592.     FloodLoop(BW, x, y, (pixel ? Clear : Set));
  593.     else if (value != pixel)
  594.     FloodLoop(BW, x, y, value); 
  595. }
  596.  
  597. #define QueryHotInMark(BW)\
  598.     ((BW->bitmap.hot.x == max(BW->bitmap.mark.from_x,\
  599.                   min(BW->bitmap.hot.x, BW->bitmap.mark.to_x)))\
  600.      &&\
  601.      (BW->bitmap.hot.y == max(BW->bitmap.mark.from_y,\
  602.                   min(BW->bitmap.hot.y, BW->bitmap.mark.to_y))))
  603.  
  604. void BWUp(w)
  605.     Widget w;
  606. {
  607.     BitmapWidget BW = (BitmapWidget) w;
  608.     register Position x, y;
  609.     bit first, up, down;
  610.     Position from_x, from_y, to_x, to_y;
  611.  
  612.     if (BWQueryMarked(w)) {
  613.     from_x = BW->bitmap.mark.from_x;
  614.     from_y = BW->bitmap.mark.from_y;
  615.     to_x = BW->bitmap.mark.to_x;
  616.     to_y = BW->bitmap.mark.to_y;
  617.     }
  618.     else {
  619.     from_x = 0;
  620.     from_y = 0;
  621.     to_x = BW->bitmap.width - 1;
  622.     to_y = BW->bitmap.height - 1;
  623.     }
  624.  
  625.     if ((to_y - from_y) == 0)
  626.     return;
  627.     
  628.     for(x = from_x; x <= to_x; x++) {
  629.     first = up = GetBit(BW->bitmap.image, x, to_y);
  630.     for(y = to_y - 1; y >= from_y; y--) {
  631.         down = GetBit(BW->bitmap.image, x, y);
  632.         if (up != down) 
  633.         InvertPoint(BW, x, y);
  634.         up =down;
  635.     }
  636.     if(first != down)
  637.         InvertPoint(BW, x, to_y);
  638.     }
  639.  
  640.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  641.     &&
  642.     !BWQueryMarked(w))
  643.     BWSetHotSpot(w,
  644.              BW->bitmap.hot.x,
  645.              (BW->bitmap.hot.y - 1 + BW->bitmap.image->height) % 
  646.              BW->bitmap.image->height);
  647.  
  648. }
  649.  
  650. void BWDown(w)
  651.     Widget w;
  652. {
  653.     BitmapWidget BW = (BitmapWidget) w;
  654.     register Position x, y;
  655.     bit first, down, up;
  656.     Position from_x, from_y, to_x, to_y;
  657.  
  658.     if (BWQueryMarked(w)) {
  659.     from_x = BW->bitmap.mark.from_x;
  660.     from_y = BW->bitmap.mark.from_y;
  661.     to_x = BW->bitmap.mark.to_x;
  662.     to_y = BW->bitmap.mark.to_y;
  663.     }
  664.     else {
  665.     from_x = 0;
  666.     from_y = 0;
  667.     to_x = BW->bitmap.width - 1;
  668.     to_y = BW->bitmap.height - 1;
  669.     }
  670.  
  671.     if ((to_y - from_y) == 0)
  672.     return;
  673.  
  674.     for(x = from_x; x <= to_x; x++) {
  675.     first = down = GetBit(BW->bitmap.image, x, from_y);
  676.     for(y = from_y + 1; y <= to_y; y++) {
  677.         up = GetBit(BW->bitmap.image, x, y);
  678.         if (down != up)
  679.         InvertPoint(BW, x, y);
  680.         down = up;
  681.     }
  682.     if(first != up) 
  683.         InvertPoint(BW, x, from_y);
  684.     }
  685.     
  686.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  687.     &&
  688.     !BWQueryMarked(w))
  689.     BWSetHotSpot(w,
  690.              BW->bitmap.hot.x,
  691.              (BW->bitmap.hot.y + 1) % BW->bitmap.image->height);
  692. }
  693.  
  694. void BWLeft(w)
  695.     Widget w;
  696. {
  697.     BitmapWidget BW = (BitmapWidget) w;
  698.     register Position x, y;
  699.     bit first, left, right;
  700.     Position from_x, from_y, to_x, to_y;
  701.     
  702.     if (BWQueryMarked(w)) {
  703.     from_x = BW->bitmap.mark.from_x;
  704.     from_y = BW->bitmap.mark.from_y;
  705.     to_x = BW->bitmap.mark.to_x;
  706.     to_y = BW->bitmap.mark.to_y;
  707.     }
  708.     else {
  709.     from_x = 0;
  710.     from_y = 0;
  711.     to_x = BW->bitmap.width - 1;
  712.     to_y = BW->bitmap.height - 1;
  713.     }
  714.  
  715.     if ((to_x - from_x) == 0)
  716.     return;
  717.     
  718.     for(y = from_y; y <= to_y; y++) {
  719.     first = left = GetBit(BW->bitmap.image, to_x, y);
  720.     for(x = to_x - 1; x >= from_x; x--) {
  721.         right = GetBit(BW->bitmap.image, x, y);
  722.         if (left != right)
  723.         InvertPoint(BW, x, y);
  724.         left = right;
  725.     }
  726.     if(first != right)
  727.         InvertPoint(BW, to_x, y);
  728.     }
  729.     
  730.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  731.     &&
  732.     !BWQueryMarked(w))
  733.     BWSetHotSpot(w,
  734.              (BW->bitmap.hot.x - 1 + BW->bitmap.image->width) % 
  735.              BW->bitmap.image->width,
  736.              BW->bitmap.hot.y);
  737. }
  738.  
  739. void BWRight(w)
  740.     Widget w;
  741. {
  742.     BitmapWidget BW = (BitmapWidget) w;
  743.     register Position x, y;
  744.     bit first, right, left;
  745.     Position from_x, from_y, to_x, to_y;
  746.     
  747.     if (BWQueryMarked(w)) {
  748.     from_x = BW->bitmap.mark.from_x;
  749.     from_y = BW->bitmap.mark.from_y;
  750.     to_x = BW->bitmap.mark.to_x;
  751.     to_y = BW->bitmap.mark.to_y;
  752.     }
  753.     else {
  754.     from_x = 0;
  755.     from_y = 0;
  756.     to_x = BW->bitmap.width - 1;
  757.     to_y = BW->bitmap.height - 1;
  758.     }
  759.     
  760.     if ((to_x - from_x) == 0)
  761.     return;
  762.     
  763.     for(y = from_y; y <= to_y; y++) {
  764.     first = right = GetBit(BW->bitmap.image, from_x, y);
  765.     for(x = from_x + 1; x <= to_x; x++) {
  766.         left = GetBit(BW->bitmap.image, x, y);
  767.         if (right != left)
  768.         InvertPoint(BW, x, y);
  769.         right = left;
  770.     }
  771.     if(first != left)
  772.         InvertPoint(BW, from_x, y);
  773.     }
  774.  
  775.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  776.     &&
  777.     !BWQueryMarked(w))
  778.     BWSetHotSpot(w,
  779.              (BW->bitmap.hot.x + 1) % BW->bitmap.image->width,
  780.              BW->bitmap.hot.y);
  781. }
  782.  
  783. void TransferImageData();
  784.  
  785. void BWFold(w)
  786.     Widget w;
  787. {
  788.     BitmapWidget BW = (BitmapWidget) w;
  789.     Position x, y, new_x, new_y;
  790.     Dimension horiz, vert;
  791.     char *storage_data;
  792.     XImage *storage;
  793.     
  794.     storage_data = CreateCleanData(Length(BW->bitmap.image->width, 
  795.                       BW->bitmap.image->height));
  796.  
  797.     storage = CreateBitmapImage(BW, storage_data, 
  798.                 (Dimension) BW->bitmap.image->width, 
  799.                 (Dimension) BW->bitmap.image->height);
  800.  
  801.     TransferImageData(BW->bitmap.image, storage);
  802.  
  803.     BW->bitmap.fold ^= True;
  804.     horiz = (BW->bitmap.image->width + BW->bitmap.fold) / 2;
  805.     vert = (BW->bitmap.image->height + BW->bitmap.fold) / 2;
  806.     
  807.     for (x = 0; x < BW->bitmap.image->width; x++)
  808.     for (y = 0; y < BW->bitmap.image->height; y++) {
  809.         new_x = (int)(x + horiz) % (int)BW->bitmap.image->width;
  810.         new_y = (int)(y + vert) % (int)BW->bitmap.image->height;
  811.         if(GetBit(BW->bitmap.image, new_x, new_y) != 
  812.            GetBit(storage, x, y))
  813.         InvertPoint(BW, new_x, new_y);
  814.     }
  815.     
  816.     DestroyBitmapImage(&storage);
  817.  
  818.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y))
  819.       BWSetHotSpot(w, 
  820.            (Position) 
  821.            ((int)(BW->bitmap.hot.x+horiz)
  822.             %(int)BW->bitmap.image->width),
  823.            (Position)
  824.            ((int)(BW->bitmap.hot.y+vert)
  825.             %(int)BW->bitmap.image->height)
  826.            );
  827. }
  828.  
  829.  
  830. void BWClear(w)
  831.     Widget w;
  832. {
  833.     BitmapWidget BW = (BitmapWidget) w;
  834.     register Position x, y;
  835.     int i, length;
  836.  
  837.     length = Length(BW->bitmap.image->width, BW->bitmap.image->height);
  838.  
  839.     for (x = 0; x < BW->bitmap.image->width; x++)
  840.     for (y = 0; y < BW->bitmap.image->height; y++)
  841.         if (GetBit(BW->bitmap.image, x, y))
  842.         DrawSquare(BW, x, y);
  843.     
  844.     for (i = 0; i < length; i++)
  845.     BW->bitmap.image->data[i] = 0;
  846.  
  847. }
  848.  
  849. void BWSet(w)
  850.     Widget w;
  851. {
  852.     BitmapWidget BW = (BitmapWidget) w;
  853.     register Position x, y;
  854.     int i, length;
  855.     
  856.     length = Length(BW->bitmap.image->width, BW->bitmap.image->height);
  857.     
  858.     for (x = 0; x < BW->bitmap.image->width; x++)
  859.     for (y = 0; y < BW->bitmap.image->height; y++)
  860.         if (!GetBit(BW->bitmap.image, x, y))
  861.         DrawSquare(BW, x, y);
  862.     
  863.     for (i = 0; i < length; i++)
  864.     BW->bitmap.image->data[i] = 255;
  865.  
  866. }
  867.  
  868. void BWRedraw(w)
  869.     Widget w;
  870. {
  871.     BitmapWidget BW = (BitmapWidget) w;
  872.  
  873.     XClearArea(XtDisplay(BW), XtWindow(BW),
  874.            0, 0, BW->core.width, BW->core.height,
  875.            True);
  876. }
  877.  
  878. void BWInvert(w)
  879.     Widget w;
  880. {
  881.     BitmapWidget BW = (BitmapWidget) w;
  882.     int i, length;
  883.  
  884.     length = Length(BW->bitmap.image->width, BW->bitmap.image->height);
  885.  
  886.     XFillRectangle(XtDisplay(BW), XtWindow(BW),
  887.            BW->bitmap.drawing_gc,
  888.            InWindowX(BW, 0), InWindowY(BW, 0),
  889.            InWindowX(BW, BW->bitmap.image->width) - InWindowX(BW, 0),
  890.            InWindowY(BW, BW->bitmap.image->height) - InWindowY(BW, 0));
  891.     
  892.     for (i = 0; i < length; i++)
  893.     BW->bitmap.image->data[i] ^= 255;
  894. }
  895.  
  896. void BWFlipHoriz(w)
  897.     Widget w;
  898. {
  899.     BitmapWidget BW = (BitmapWidget) w;
  900.     register Position x, y;
  901.     Position from_x, from_y, to_x, to_y;
  902.     float half;
  903.     
  904.     if (BWQueryMarked(w)) {
  905.     from_x = BW->bitmap.mark.from_x;
  906.     from_y = BW->bitmap.mark.from_y;
  907.     to_x = BW->bitmap.mark.to_x;
  908.     to_y = BW->bitmap.mark.to_y;
  909.     }
  910.     else {
  911.     from_x = 0;
  912.     from_y = 0;
  913.     to_x = BW->bitmap.width - 1;
  914.     to_y = BW->bitmap.height - 1;
  915.     }
  916.     half = (float) (to_y - from_y) / 2.0 + 0.5;
  917.     
  918.     if (half == 0.0)
  919.     return;
  920.     
  921.     for (x = from_x; x <= to_x; x++) 
  922.     for (y = 0; y <  half; y++)
  923.         if (GetBit(BW->bitmap.image, x, from_y + y) != 
  924.         GetBit(BW->bitmap.image, x, to_y - y)) {
  925.         InvertPoint(BW, x, from_y + y);
  926.         InvertPoint(BW, x, to_y - y);
  927.         }
  928.     
  929.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  930.     &&
  931.     !BWQueryMarked(w))
  932.     BWSetHotSpot(w,
  933.              BW->bitmap.hot.x,
  934.              BW->bitmap.image->height - 1 - BW->bitmap.hot.y);
  935. }
  936.  
  937. void BWFlipVert(w)
  938.     Widget w;
  939. {
  940.     BitmapWidget BW = (BitmapWidget) w;
  941.     register Position x, y;
  942.     Position from_x, from_y, to_x, to_y;
  943.     float half;
  944.     
  945.     if (BWQueryMarked(w)) {
  946.     from_x = BW->bitmap.mark.from_x;
  947.     from_y = BW->bitmap.mark.from_y;
  948.     to_x = BW->bitmap.mark.to_x;
  949.     to_y = BW->bitmap.mark.to_y;
  950.     }
  951.     else {
  952.     from_x = 0;
  953.     from_y = 0;
  954.     to_x = BW->bitmap.width - 1;
  955.     to_y = BW->bitmap.height - 1;
  956.     }
  957.     half = (float) (to_x - from_x) / 2.0 + 0.5;
  958.  
  959.     if (half == 0)
  960.     return;
  961.  
  962.     for (y = from_y; y <= to_y; y++)
  963.     for (x = 0; x < half; x++)
  964.         if (GetBit(BW->bitmap.image, from_x + x, y) != 
  965.         GetBit(BW->bitmap.image, to_x - x, y)) {
  966.         InvertPoint(BW, from_x + x, y);
  967.         InvertPoint(BW, to_x - x, y);
  968.         }
  969.     
  970.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  971.     &&
  972.     !BWQueryMarked(w))
  973.     BWSetHotSpot(w,
  974.              BW->bitmap.image->width - 1 - BW->bitmap.hot.x,
  975.              BW->bitmap.hot.y);
  976. }
  977.  
  978.  
  979. void BWRotateRight(w)
  980.     Widget w;
  981. {
  982.     BitmapWidget BW = (BitmapWidget) w;
  983.     Position x, y, delta, shift, tmp;
  984.     Position half_width, half_height;
  985.     XPoint hot;
  986.     bit quad1, quad2, quad3, quad4;
  987.     Position from_x, from_y, to_x, to_y;
  988.     
  989.     if (BWQueryMarked(w)) {
  990.     from_x = BW->bitmap.mark.from_x;
  991.     from_y = BW->bitmap.mark.from_y;
  992.     to_x = BW->bitmap.mark.to_x;
  993.     to_y = BW->bitmap.mark.to_y;
  994.     }
  995.     else {
  996.     from_x = 0;
  997.     from_y = 0;
  998.     to_x = BW->bitmap.width - 1;
  999.     to_y = BW->bitmap.height - 1;
  1000.     }
  1001.  
  1002.     half_width = floor((to_x - from_x) / 2.0 + 0.5);
  1003.     half_height = floor((to_y - from_y ) / 2.0 + 0.5);
  1004.     shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2;
  1005.     delta = min((Position) half_width, (Position) half_height) - shift;
  1006.     
  1007.     for (x = 0; x <= delta; x++) {
  1008.     for (y = 1 - shift; y <= delta; y++) {
  1009.         quad1 = GetBit(BW->bitmap.image, 
  1010.                from_x + (Position)half_width + x, 
  1011.                from_y + (Position)half_height + y);
  1012.         quad2 = GetBit(BW->bitmap.image, 
  1013.                from_x + (Position)half_width + y, 
  1014.                from_y + (Position)half_height - shift - x);
  1015.         quad3 = GetBit(BW->bitmap.image, 
  1016.                from_x + (Position)half_width - shift - x, 
  1017.                from_y + (Position)half_height - shift - y);
  1018.         quad4 = GetBit(BW->bitmap.image, 
  1019.                from_x + (Position)half_width - shift - y, 
  1020.                from_y + (Position)half_height + x);
  1021.  
  1022.         if (quad1 != quad2)
  1023.         InvertPoint(BW, 
  1024.                 from_x + (Position)half_width + x, 
  1025.                 from_y + (Position)half_height + y);
  1026.         if (quad2 != quad3)
  1027.         InvertPoint(BW, 
  1028.                 from_x + (Position)half_width + y, 
  1029.                 from_y + (Position)half_height - shift - x);
  1030.         if (quad3 != quad4)
  1031.         InvertPoint(BW, 
  1032.                 from_x + (Position)half_width - shift - x,
  1033.                 from_y + (Position)half_height - shift - y);
  1034.         if (quad4 != quad1)
  1035.         InvertPoint(BW, 
  1036.                 from_x + (Position)half_width - shift - y, 
  1037.                 from_y + (Position)half_height + x);
  1038.     }
  1039.     }
  1040.     
  1041.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  1042.     &&
  1043.     !BWQueryMarked(w)) {
  1044.     hot.x = BW->bitmap.hot.x - half_width;
  1045.     hot.y = BW->bitmap.hot.y - half_height;
  1046.     if (hot.x >= 0) hot.x += shift;
  1047.     if (hot.y >= 0) hot.y += shift;
  1048.     tmp = hot.x;
  1049.     hot.x = - hot.y;
  1050.     hot.y = tmp;
  1051.     if (hot.x > 0) hot.x -= shift;
  1052.     if (hot.y > 0) hot.y -= shift;
  1053.     hot.x += half_width;
  1054.     hot.y += half_height;
  1055.     if (QueryInBitmap(BW, hot.x, hot.y))
  1056.         BWSetHotSpot(w, hot.x, hot.y);
  1057.     }
  1058.     
  1059. }
  1060.  
  1061. void BWRotateLeft(w)
  1062.     Widget w;
  1063. {
  1064.     BitmapWidget BW = (BitmapWidget) w;
  1065.     Position x, y,delta, shift, tmp;
  1066.     Position half_width, half_height;
  1067.     XPoint hot;
  1068.     bit quad1, quad2, quad3, quad4;
  1069.     Position from_x, from_y, to_x, to_y;
  1070.     
  1071.     if (BWQueryMarked(w)) {
  1072.     from_x = BW->bitmap.mark.from_x;
  1073.     from_y = BW->bitmap.mark.from_y;
  1074.     to_x = BW->bitmap.mark.to_x;
  1075.     to_y = BW->bitmap.mark.to_y;
  1076.     }
  1077.     else {
  1078.     from_x = 0;
  1079.     from_y = 0;
  1080.     to_x = BW->bitmap.width - 1;
  1081.     to_y = BW->bitmap.height - 1;
  1082.     }
  1083.  
  1084.     half_width = floor((to_x - from_x) / 2.0 + 0.5);
  1085.     half_height = floor((to_y - from_y ) / 2.0 + 0.5);
  1086.     shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2;
  1087.     delta = min((Position) half_width, (Position) half_height) - shift;
  1088.     
  1089.     for (x = 0; x <= delta; x++) {
  1090.     for (y = 1 - shift; y <= delta; y++) {
  1091.         quad1 = GetBit(BW->bitmap.image, 
  1092.                from_x + (Position)half_width + x, 
  1093.                from_y + (Position)half_height + y);
  1094.         quad2 = GetBit(BW->bitmap.image, 
  1095.                from_x + (Position)half_width + y, 
  1096.                from_y + (Position)half_height - shift - x);
  1097.         quad3 = GetBit(BW->bitmap.image, 
  1098.                from_x + (Position)half_width - shift - x, 
  1099.                from_y + (Position)half_height - shift - y);
  1100.         quad4 = GetBit(BW->bitmap.image, 
  1101.                from_x + (Position)half_width - shift - y, 
  1102.                from_y + (Position)half_height + x);
  1103.  
  1104.         if (quad1 != quad4)
  1105.         InvertPoint(BW, 
  1106.                 from_x + (Position)half_width + x, 
  1107.                 from_y + (Position)half_height + y);
  1108.         if (quad2 != quad1)
  1109.         InvertPoint(BW, 
  1110.                 from_x + (Position)half_width + y, 
  1111.                 from_y + (Position)half_height - shift - x);
  1112.         if (quad3 != quad2)
  1113.         InvertPoint(BW, 
  1114.                 from_x + (Position)half_width - shift - x,
  1115.                 from_y + (Position)half_height - shift - y);
  1116.         if (quad4 != quad3)
  1117.         InvertPoint(BW, 
  1118.                 from_x + (Position)half_width - shift - y, 
  1119.                 from_y + (Position)half_height + x);
  1120.     }
  1121.     }
  1122.     
  1123.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  1124.     &&
  1125.     !BWQueryMarked(w)) {
  1126.     hot.x = BW->bitmap.hot.x - half_width;
  1127.     hot.y = BW->bitmap.hot.y - half_height;
  1128.     if (hot.x >= 0) hot.x += shift;
  1129.     if (hot.y >= 0) hot.y += shift;
  1130.     tmp = hot.x;
  1131.     hot.x = hot.y;
  1132.     hot.y = - tmp;
  1133.     if (hot.x > 0) hot.x -= shift;
  1134.     if (hot.y > 0) hot.y -= shift;
  1135.     hot.x += half_width;
  1136.     hot.y += half_height;
  1137.     if (QueryInBitmap(BW, hot.x, hot.y))
  1138.         BWSetHotSpot(w, hot.x, hot.y);
  1139.     }
  1140. }
  1141.  
  1142.  
  1143. void CopyImageData(source, destination, from_x, from_y, to_x, to_y, at_x, at_y)
  1144.     XImage *source, *destination;
  1145.     Position  from_x, from_y, to_x, to_y, at_x, at_y;
  1146. {
  1147.     Position x, y, delta_x, delta_y;
  1148.     
  1149.     delta_x = to_x - from_x + 1;
  1150.     delta_y = to_y - from_y + 1;
  1151.     
  1152.     for (x = 0; x < delta_x; x++)
  1153.     for (y = 0; y < delta_y; y++)
  1154.         if (GetBit(source, from_x + x, from_y + y))
  1155.         SetBit(destination, at_x + x, at_y + y);
  1156.         else
  1157.         ClearBit(destination, at_x + x, at_y + y);
  1158. }
  1159.       
  1160. XImage *ConvertToBitmapImage(BW, image)
  1161.     BitmapWidget BW;
  1162.     XImage *image;
  1163. {
  1164.     XImage *bitmap_image;
  1165.     char   *data;
  1166.     Position x, y;
  1167.     
  1168.     data = CreateCleanData(Length(image->width, image->height));
  1169.     bitmap_image = CreateBitmapImage(BW, data, 
  1170.                      (Dimension) image->width, 
  1171.                      (Dimension) image->height);
  1172.  
  1173.     for (x = 0; x < min(image->width, bitmap_image->width); x++)
  1174.     for (y = 0; y < min(image->height, bitmap_image->height); y++)
  1175.         if ((XGetPixel(image, x, y) != 0) != GetBit(bitmap_image, x, y))
  1176.         InvertBit(bitmap_image, x, y);
  1177.  
  1178.     return bitmap_image;
  1179. }
  1180.  
  1181. void TransferImageData(source, destination)
  1182.     XImage *source, *destination;
  1183. {
  1184.     Position x, y;
  1185.     
  1186.     for (x = 0; x < min(source->width, destination->width); x++)
  1187.     for (y = 0; y < min(source->height, destination->height); y++)
  1188.         if (GetBit(source, x, y) != GetBit(destination, x, y))
  1189.         InvertBit(destination, x, y);
  1190. }
  1191.  
  1192. void BWStore(w)
  1193.     Widget w;
  1194. {
  1195.     BitmapWidget BW = (BitmapWidget) w;
  1196.     Dimension width, height;
  1197.     char *storage_data;
  1198.  
  1199.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
  1200.  
  1201.     DestroyBitmapImage(&BW->bitmap.storage);
  1202.  
  1203.     width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1;
  1204.     height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1;
  1205.     
  1206.     storage_data = CreateCleanData(Length(width, height));
  1207.  
  1208.     BW->bitmap.storage = CreateBitmapImage(BW,
  1209.                            storage_data,
  1210.                            width, height);
  1211.  
  1212.     CopyImageData(BW->bitmap.image, BW->bitmap.storage,
  1213.               BW->bitmap.mark.from_x,  BW->bitmap.mark.from_y,
  1214.               BW->bitmap.mark.to_x,  BW->bitmap.mark.to_y,
  1215.               0, 0);
  1216.     }
  1217. }
  1218.  
  1219. void BWClearMarked(w)
  1220.     Widget w;
  1221. {
  1222.     BitmapWidget BW = (BitmapWidget) w;
  1223.     
  1224.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y))
  1225.     BWDrawFilledRectangle(w,
  1226.                   BW->bitmap.mark.from_x,
  1227.                   BW->bitmap.mark.from_y,
  1228.                   BW->bitmap.mark.to_x,
  1229.                   BW->bitmap.mark.to_y,
  1230.                   Clear);
  1231. }
  1232.  
  1233.  
  1234. void BWDragMarked(w, at_x, at_y)
  1235.     Widget w;
  1236.     Position     at_x, at_y;
  1237. {
  1238.     BitmapWidget BW = (BitmapWidget) w;
  1239.  
  1240.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y))
  1241.     BWDrawRectangle(w, 
  1242.             at_x, at_y, 
  1243.             at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x,
  1244.             at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y,
  1245.             Highlight);
  1246. }
  1247.  
  1248. void BWDragStored(w, at_x, at_y)
  1249.     Widget       w;
  1250.     Position     at_x, at_y;
  1251. {
  1252.     BitmapWidget BW = (BitmapWidget) w;
  1253.     
  1254.     if (BW->bitmap.storage)
  1255.     BWDrawRectangle(w, 
  1256.             at_x, at_y,
  1257.             at_x + BW->bitmap.storage->width - 1,
  1258.             at_y + BW->bitmap.storage->height - 1,
  1259.             Highlight);
  1260. }
  1261.  
  1262. void DrawImageData(BW, image, at_x, at_y, value)
  1263.     BitmapWidget BW;
  1264.     XImage       *image;
  1265.     Position     at_x, at_y;
  1266.     int          value;
  1267. {
  1268.     Position x, y;
  1269.     Boolean  C, S, I, H;
  1270.     bit      A, B;
  1271.  
  1272.     C = value == Clear;
  1273.     S = value == Set;
  1274.     I = value == Invert;
  1275.     H = value == Highlight;
  1276.  
  1277.     for (x = 0; x < image->width; x++) 
  1278.     for (y = 0; y < image->height; y++) {
  1279.         A = GetBit(image, x, y);
  1280.         B = GetBit(BW->bitmap.image, at_x + x, at_y + y);
  1281.         if (A & C | (A | B) & S | (A ^ B) & I | (A | B) & H)
  1282.         value = (A & H) ? Highlight : Set;
  1283.         else
  1284.         value = Clear;
  1285.         BWDrawPoint((Widget) BW, 
  1286.              at_x + x, at_y + y, 
  1287.              value);
  1288.     }
  1289. }
  1290.  
  1291. void BWRestore(w, at_x, at_y, value)
  1292.     Widget       w;
  1293.     Position     at_x, at_y;
  1294.     int          value;
  1295. {
  1296.     BitmapWidget BW = (BitmapWidget) w;
  1297.     
  1298.     if (BW->bitmap.storage) {
  1299.       DrawImageData(BW, BW->bitmap.storage, at_x, at_y, value);
  1300.       /*DestroyBitmapImage(&BW->bitmap.storage);*/
  1301.     }
  1302. }
  1303.  
  1304. void BWCopy(w, at_x, at_y, value)
  1305.     Widget       w;
  1306.     Position     at_x, at_y;
  1307.     int          value;
  1308. {
  1309.     BitmapWidget BW = (BitmapWidget) w;
  1310.     XImage *storage;
  1311.     char *storage_data;
  1312.     Dimension width, height;
  1313.  
  1314.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
  1315.  
  1316.     width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1;
  1317.     height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1;
  1318.     
  1319.     storage_data = CreateCleanData(Length(width, height));
  1320.  
  1321.     storage = CreateBitmapImage(BW, storage_data, width, height);
  1322.  
  1323.     CopyImageData(BW->bitmap.image, storage,
  1324.               BW->bitmap.mark.from_x,  BW->bitmap.mark.from_y,
  1325.               BW->bitmap.mark.to_x,  BW->bitmap.mark.to_y,
  1326.               0, 0);
  1327.  
  1328.     DrawImageData(BW, storage, at_x, at_y, value);
  1329.  
  1330.     DestroyBitmapImage(&storage);
  1331.     }
  1332. }
  1333.  
  1334. void BWMark();
  1335.  
  1336. void BWMove(w, at_x, at_y, value)
  1337.     Widget   w;
  1338.     Position at_x, at_y;
  1339.     int      value;
  1340. {
  1341.     BitmapWidget BW = (BitmapWidget) w;
  1342.     XImage *storage;
  1343.     char *storage_data;
  1344.     Dimension width, height;
  1345.  
  1346.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
  1347.  
  1348.     width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1;
  1349.     height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1;
  1350.     
  1351.     storage_data = CreateCleanData(Length(width, height));
  1352.  
  1353.     storage = CreateBitmapImage(BW, storage_data, width, height);
  1354.  
  1355.     CopyImageData(BW->bitmap.image, storage,
  1356.               BW->bitmap.mark.from_x,  BW->bitmap.mark.from_y,
  1357.               BW->bitmap.mark.to_x,  BW->bitmap.mark.to_y,
  1358.               0, 0);
  1359.  
  1360.     BWDrawFilledRectangle(w,
  1361.                   BW->bitmap.mark.from_x, BW->bitmap.mark.from_y,
  1362.                   BW->bitmap.mark.to_x, BW->bitmap.mark.to_y,
  1363.                   Clear);
  1364.  
  1365.     DrawImageData(BW, storage, at_x, at_y, value);
  1366.  
  1367.     BWMark(w, at_x, at_y,
  1368.          at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x,
  1369.          at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y);
  1370.  
  1371.     DestroyBitmapImage(&storage);
  1372.     }
  1373. }
  1374.  
  1375. void BWRedrawMark(w)
  1376.     Widget w;
  1377. {
  1378.     BitmapWidget BW = (BitmapWidget) w;
  1379.     
  1380.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) 
  1381.     XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,
  1382.                InWindowX(BW, BW->bitmap.mark.from_x), 
  1383.                InWindowY(BW, BW->bitmap.mark.from_y), 
  1384.                InWindowX(BW, BW->bitmap.mark.to_x + 1) - 
  1385.                InWindowX(BW, BW->bitmap.mark.from_x),
  1386.                InWindowY(BW, BW->bitmap.mark.to_y + 1) -
  1387.                InWindowY(BW, BW->bitmap.mark.from_y));
  1388. }
  1389.  
  1390. void BWStoreToBuffer(w)
  1391.      Widget w;
  1392. {
  1393.     BitmapWidget BW = (BitmapWidget) w;
  1394.     
  1395.     bcopy(BW->bitmap.image->data, BW->bitmap.buffer->data,
  1396.       Length(BW->bitmap.image->width, BW->bitmap.image->height));
  1397.  
  1398.     BW->bitmap.buffer_hot = BW->bitmap.hot;
  1399.     BW->bitmap.buffer_mark = BW->bitmap.mark;
  1400. }
  1401.  
  1402. void BWUnmark(w)
  1403.      Widget w;
  1404. {
  1405.     BitmapWidget BW = (BitmapWidget) w;
  1406.  
  1407.     BW->bitmap.buffer_mark = BW->bitmap.mark;
  1408.  
  1409.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
  1410.     XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,
  1411.                InWindowX(BW, BW->bitmap.mark.from_x), 
  1412.                InWindowY(BW, BW->bitmap.mark.from_y), 
  1413.                InWindowX(BW, BW->bitmap.mark.to_x + 1) - 
  1414.                InWindowX(BW, BW->bitmap.mark.from_x),
  1415.                InWindowY(BW, BW->bitmap.mark.to_y + 1) -
  1416.                InWindowY(BW, BW->bitmap.mark.from_y));
  1417.     
  1418.     BW->bitmap.mark.from_x = BW->bitmap.mark.from_y = NotSet;
  1419.     BW->bitmap.mark.to_x = BW->bitmap.mark.to_y = NotSet;
  1420.     }
  1421. }
  1422.  
  1423. void BWMark(w, from_x, from_y, to_x, to_y)
  1424.     Widget w;
  1425.     Position from_x, from_y,
  1426.          to_x, to_y;
  1427. {
  1428.     BitmapWidget BW = (BitmapWidget) w;
  1429.  
  1430.     BWUnmark(w);
  1431.     
  1432.     if (QuerySet(from_x, from_y)) {
  1433.     if ((from_x == to_x) && (from_y == to_y)) {
  1434.         /*
  1435.           BW->bitmap.mark.from_x = 0;
  1436.           BW->bitmap.mark.from_y = 0;
  1437.           BW->bitmap.mark.to_x = BW->bitmap.image->width - 1;
  1438.           BW->bitmap.mark.to_y = BW->bitmap.image->height - 1;
  1439.           */
  1440.         return;
  1441.     }
  1442.     else {
  1443.         QuerySwap(from_x, to_x);
  1444.         QuerySwap(from_y, to_y);
  1445.         from_x = max(0, from_x);
  1446.         from_y = max(0, from_y);
  1447.         to_x = min(BW->bitmap.image->width - 1, to_x);
  1448.         to_y = min(BW->bitmap.image->height - 1, to_y);
  1449.         
  1450.         BW->bitmap.mark.from_x = from_x;
  1451.         BW->bitmap.mark.from_y = from_y;
  1452.         BW->bitmap.mark.to_x = to_x;
  1453.         BW->bitmap.mark.to_y = to_y;
  1454.     }
  1455.     
  1456.     XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,
  1457.                InWindowX(BW, BW->bitmap.mark.from_x),
  1458.                InWindowY(BW, BW->bitmap.mark.from_y), 
  1459.                InWindowX(BW, BW->bitmap.mark.to_x + 1) -
  1460.                InWindowX(BW, BW->bitmap.mark.from_x),
  1461.                InWindowY(BW, BW->bitmap.mark.to_y +1) - 
  1462.                InWindowY(BW, BW->bitmap.mark.from_y));
  1463.     }
  1464. }
  1465.  
  1466. void BWMarkAll(w)
  1467.     Widget w;
  1468. {
  1469.   BitmapWidget BW = (BitmapWidget) w;
  1470.  
  1471.   BWMark(w, 0, 0, BW->bitmap.image->width - 1, BW->bitmap.image->height - 1);
  1472. }
  1473.  
  1474. void BWUndo(w)
  1475.     Widget w;
  1476. {
  1477.     BitmapWidget BW = (BitmapWidget) w;
  1478.     Position x, y;
  1479.     char *tmp_data;
  1480.     XPoint tmp_hot;
  1481.     BWArea tmp_mark;
  1482.     
  1483.     tmp_data = BW->bitmap.image->data;
  1484.     BW->bitmap.image->data = BW->bitmap.buffer->data;
  1485.     BW->bitmap.buffer->data = tmp_data;
  1486.  
  1487.     tmp_hot = BW->bitmap.hot;
  1488.     tmp_mark = BW->bitmap.mark;
  1489.     
  1490.     for (x = 0; x < BW->bitmap.image->width; x++)
  1491.     for (y = 0; y < BW->bitmap.image->height; y++)
  1492.      if (GetBit(BW->bitmap.image, x, y) != GetBit(BW->bitmap.buffer, x, y))
  1493.          DrawSquare(BW, x, y);
  1494.  
  1495.     BWSetHotSpot(w, BW->bitmap.buffer_hot.x, BW->bitmap.buffer_hot.y);
  1496. /*    
  1497.     BWMark(w, BW->bitmap.buffer_mark.from_x, BW->bitmap.buffer_mark.from_y,
  1498.        BW->bitmap.buffer_mark.to_x, BW->bitmap.buffer_mark.to_y);
  1499. */
  1500.     BW->bitmap.buffer_hot = tmp_hot;
  1501.     BW->bitmap.buffer_mark= tmp_mark;
  1502.  
  1503. }
  1504.  
  1505. void BWHighlightAxes(w)
  1506.     Widget w;
  1507. {
  1508.     BitmapWidget BW = (BitmapWidget) w;
  1509.  
  1510.     XDrawLine(XtDisplay(BW), XtWindow(BW),
  1511.           BW->bitmap.axes_gc,
  1512.           InWindowX(BW, 0), 
  1513.           InWindowY(BW, 0),
  1514.           InWindowX(BW, BW->bitmap.width),
  1515.           InWindowY(BW, BW->bitmap.height));
  1516.     XDrawLine(XtDisplay(BW), XtWindow(BW),
  1517.           BW->bitmap.axes_gc,
  1518.           InWindowX(BW, BW->bitmap.width),
  1519.           InWindowY(BW, 0), 
  1520.           InWindowX(BW, 0),
  1521.           InWindowY(BW, BW->bitmap.height));
  1522.     XDrawLine(XtDisplay(BW), XtWindow(BW),
  1523.           BW->bitmap.axes_gc,
  1524.           InWindowX(BW, 0),
  1525.           InWindowY(BW, (float)BW->bitmap.height / 2.0),
  1526.           InWindowX(BW, BW->bitmap.width),
  1527.           InWindowY(BW, (float)BW->bitmap.height / 2.0));
  1528.     XDrawLine(XtDisplay(BW), XtWindow(BW),
  1529.           BW->bitmap.axes_gc,
  1530.           InWindowX(BW, (float)BW->bitmap.width / 2.0),
  1531.           InWindowY(BW, 0),
  1532.           InWindowX(BW, (float)BW->bitmap.width / 2.0),
  1533.           InWindowY(BW, BW->bitmap.height));
  1534. }
  1535.     
  1536. typedef struct {
  1537.     Position *x, *y;
  1538.     Dimension *width, *height;
  1539. } Table;
  1540.  
  1541. XImage *ScaleBitmapImage(BW, src, scale_x, scale_y)
  1542.     BitmapWidget BW;
  1543.     XImage *src;
  1544.     double scale_x, scale_y;
  1545. {
  1546.     char *data;
  1547.     XImage *dst;
  1548.     Table table;    
  1549.     Position x, y, w, h;
  1550.     Dimension width, height;
  1551.     bit pixel;
  1552.  
  1553.     width = max(rint(scale_x * src->width), 1);
  1554.     height = max(rint(scale_y * src->height), 1);
  1555.  
  1556.     data = CreateCleanData(Length(width, height));
  1557.     dst = CreateBitmapImage(BW, data, width, height);
  1558.  
  1559.     /*
  1560.      * It would be nice to check if width or height < 1.0 and
  1561.      * average the skipped pixels. But, it is slow as it is now.
  1562.      */
  1563.     if (scale_x == 1.0 && scale_y == 1.0)
  1564.     bcopy (src->data, dst->data, Length(width, height));
  1565.     else {
  1566.     table.x = (Position *) XtMalloc(sizeof(Position) * src->width);
  1567.     table.y = (Position *) XtMalloc(sizeof(Position) * src->height);
  1568.     table.width = (Dimension *) XtMalloc(sizeof(Dimension) * src->width);
  1569.     table.height = (Dimension *) XtMalloc(sizeof(Dimension) * src->height);
  1570.     
  1571.     for (x = 0; x < src->width; x++) {
  1572.         table.x[x] = rint(scale_x * x);
  1573.         table.width[x] = rint(scale_x * (x + 1)) - rint(scale_x * x);
  1574.     }
  1575.     for (y = 0; y < src->height; y++) {
  1576.         table.y[y] = rint(scale_y * y);
  1577.         table.height[y] = rint(scale_y * (y + 1)) - rint(scale_y * y);
  1578.     }
  1579.     
  1580.     for (x = 0; x < src->width; x++)
  1581.         for (y = 0; y < src->height; y++) {
  1582.             pixel = GetBit(src, x, y);
  1583.         for (w = 0; (int)w < (int)table.width[x]; w++)
  1584.             for (h = 0; (int)h < (int)table.height[y]; h++)
  1585.             if (pixel) SetBit(dst, 
  1586.                     table.x[x] + w, 
  1587.                     table.y[y] + h);
  1588.         }
  1589.  
  1590.     XtFree((char *)table.x);
  1591.     XtFree((char *)table.y);
  1592.     XtFree((char *)table.width);
  1593.     XtFree((char *)table.height);
  1594.     }
  1595.     
  1596.     return (dst);
  1597. }
  1598.  
  1599. /*****************************************************************************/
  1600.